﻿using FluorineFx.Json;
using lxwmvc;
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Drawing.Imaging;
using System.IO;
using System.Text;
using System.Web;

namespace lxwmvc
{
    /// <summary>
    /// 生成验证码 二维码 和 极限验证
    /// </summary>
    public class WeiXin_Code
    {
        #region 验证码 生成代码

        /// <summary>
        /// 随机字符串
        /// </summary>
        private const string strValidateCodeBound = "abcdefghijkmnpqrstuvwxyzABCDEFGHIJKLMNPQRSTUVWXYZ23456789";
        //private const string strValidateCodeBound = "123456789";
        //private const string strValidateCodeBound = "丅丆乁乀乂丄屮匚垚靐厽馫飍灥厵麤毳龘骉驫羴雥鱻矗奸舙瞐掱叒譶劦壵孨歮飝刕嚞皛雦朤燚叕茻";
        /// <summary>
        /// 随机字体
        /// </summary>
        private static string[] Fonts = new string[] { "Helvetica", "Geneva", "sans-serif", "Verdana", "Times New Roman", "Courier New", "Arial" };
        //private static string[] Fonts = new string[] { "Helvetica", "方正硬笔楷书简体" };

        /// <summary>
        /// 随机字符串生成
        /// </summary>
        /// <param name="int_NumberLength"></param>
        /// <returns></returns>
        public static string GetRandomString(int int_NumberLength)
        {
            string valString = string.Empty;
            Random theRandomNumber = new Random((int)DateTime.Now.Ticks);

            for (int int_index = 0; int_index < int_NumberLength; int_index++)
                valString += strValidateCodeBound[theRandomNumber.Next(strValidateCodeBound.Length - 1)].ToString();

            return valString;
        }

        /// <summary>
        /// 验证码生成
        /// </summary>
        /// <param name="str_ValidateCode">验证码字符串</param>
        /// <param name="width">单字宽度</param>
        /// <param name="height">输出图片高度</param>
        /// <returns>验证码PNG流</returns>
        public static MemoryStream CreateImage(string str_ValidateCode, int width = 32, int height = 64)
        {
            int int_ImageWidth = str_ValidateCode.Length * width;
            Random newRandom = new Random();

            Bitmap theBitmap = new Bitmap(int_ImageWidth, height);

            Graphics theGraphics = Graphics.FromImage(theBitmap);
            theGraphics.Clear(Color.White);
            int PixelArea = int_ImageWidth * height;
            drawLine(theGraphics, theBitmap, newRandom, PixelArea);
            theGraphics.DrawRectangle(new Pen(Color.LightGray, 1), 0, 0, theBitmap.Width - 1, theBitmap.Height - 1);

            for (int int_index = 0; int_index < str_ValidateCode.Length; int_index++)
            {
                Matrix X = new Matrix();
                X.Shear((float)newRandom.Next(0, 300) / 1000 - 0.25f, (float)newRandom.Next(0, 100) / 1000 - 0.05f);
                theGraphics.Transform = X;
                string str_char = str_ValidateCode.Substring(int_index, 1);
                System.Drawing.Drawing2D.LinearGradientBrush newBrush = new System.Drawing.Drawing2D.LinearGradientBrush(new Rectangle(0, 0, theBitmap.Width, theBitmap.Height), Color.FromArgb(0, 0, newRandom.Next(0, 255)), Color.FromArgb(newRandom.Next(0, 255), 0, 0), 1.2f, true);
                Point thePos = new Point(int_index * width + 1 + newRandom.Next(3), 1 + newRandom.Next(13));

                //Font theFont = new Font(Fonts[newRandom.Next(Fonts.Length - 1)], newRandom.Next(24, 36), FontStyle.Bold);//文字大小 24-36
                Font theFont = new Font(Fonts[newRandom.Next(Fonts.Length - 1)], newRandom.Next((height / 3).toint32(), (height / 2).toint32()), FontStyle.Bold);
                theGraphics.DrawString(str_char, theFont, newBrush, thePos);
            }
            drawPoint(theBitmap, newRandom, PixelArea / width);

            MemoryStream ms = new MemoryStream();
            theBitmap.Save(ms, ImageFormat.Jpeg);

            if (theBitmap!=null) theBitmap.Dispose();

            return ms;
            //Response.ClearContent();
            //Response.ContentType = "image/Png";
            //Response.BinaryWrite(ms.ToArray());
            //theGraphics.Dispose();
            //theBitmap.Dispose();
            //Response.End();
        }

        /// <summary>
        /// 画噪声线
        /// </summary>
        /// <param name="gfc"></param>
        /// <param name="img"></param>
        /// <param name="ran"></param>
        /// <param name="item">高度64 推荐画20条</param>
        private static void drawLine(Graphics gfc, Bitmap img, Random ran, int PixelArea)
        {
            for (int i = 0; i < 20; i++)
            {
                int x1 = ran.Next(img.Width);
                int y1 = ran.Next(img.Height);
                int x2 = ran.Next(img.Width);
                int y2 = ran.Next(img.Height);
                gfc.DrawLine(new Pen(Color.FromArgb(ran.Next(50, 150), 0, 0, ran.Next(0, 255)), ran.Next(PixelArea / 16384, PixelArea / 1024)), x1, y1, x2, y2);

            }
        }

        /// <summary>
        /// 画噪声点
        /// </summary>
        /// <param name="img"></param>
        /// <param name="ran"></param>
        /// <param name="num">输出宽度多少 就花多少 例如32*4=128</param>
        private static void drawPoint(Bitmap img, Random ran, int num)
        {
            for (int i = 0; i < num; i++)
            {
                int x = ran.Next(img.Width);
                int y = ran.Next(img.Height);
                img.SetPixel(x, y, Color.FromArgb(0, 0, ran.Next(0, 255)));

            }

        }

        #endregion


        #region 生成二维码

        /// <summary>
        /// 生成文本 图片 (带谢谢参与)
        /// </summary>
        /// <param name="pb"></param>
        public static MemoryStream photo(string text, int wh = 12, string font = "微软雅黑", string color = "#FFFFFF", string bgcolor = "#FE6D58", int fontsize = 10)
        {
            wh = wh * 64;
            Bitmap theBitmap = new Bitmap(wh, wh);
            Graphics theGraphics = Graphics.FromImage(theBitmap);
            theGraphics.Clear(ColorTranslator.FromHtml(bgcolor));
            SolidBrush sdBrush1 = new SolidBrush(ColorTranslator.FromHtml(color));

            System.Drawing.Drawing2D.LinearGradientBrush newBrush = new System.Drawing.Drawing2D.LinearGradientBrush(new Rectangle(0, 0, theBitmap.Width, theBitmap.Height), ColorTranslator.FromHtml(color), ColorTranslator.FromHtml(color), 1.2f, true);

            Font theFont = new Font(font, wh / fontsize, FontStyle.Bold);

            Point thePos = new Point(wh / 2, wh / 2);
            StringFormat sf = new StringFormat();
            sf.LineAlignment = StringAlignment.Center;
            sf.Alignment = StringAlignment.Center;
            theGraphics.DrawString(text, theFont, sdBrush1, thePos, sf);

            //theGraphics.DrawString("谢谢参与", theFont, sdBrush1, 20, 40);
            //theGraphics.DrawString(text, theFont, sdBrush1, 10, theFont.Height+40);

            MemoryStream ms = new MemoryStream();
            theBitmap.Save(ms, ImageFormat.Png);

            if (theBitmap != null) theBitmap.Dispose();
            return ms;
        }



        /// <summary>
        /// 生成二维码
        /// </summary>
        /// <param name="pb"></param>
        public static MemoryStream erweima(string text, int size = 12, string geshi = "png", string color = "#000000", string bgcolor = "#FFFFFF", int bian = 0)
        {
            if (string.IsNullOrEmpty(text)) text = "请设置内容!";
            if (size == 0) size = 12;

            Gma.QrCodeNet.Encoding.Windows.Render.QuietZoneModules quietZoneModules = (Gma.QrCodeNet.Encoding.Windows.Render.QuietZoneModules)bian;

            //设置容错级别。
            Gma.QrCodeNet.Encoding.QrEncoder qrEncoder = new Gma.QrCodeNet.Encoding.QrEncoder(Gma.QrCodeNet.Encoding.ErrorCorrectionLevel.H);


            Gma.QrCodeNet.Encoding.QrCode qrCode = new Gma.QrCodeNet.Encoding.QrCode();

            qrEncoder.TryEncode(text, out qrCode);

            var renderer = new Gma.QrCodeNet.Encoding.Windows.Render.GraphicsRenderer(
                new Gma.QrCodeNet.Encoding.Windows.Render.FixedModuleSize(size.toint32(), quietZoneModules)
                , new System.Drawing.SolidBrush(System.Drawing.ColorTranslator.FromHtml(color)),
                 new System.Drawing.SolidBrush(System.Drawing.ColorTranslator.FromHtml(bgcolor))
                );

            MemoryStream ms = new MemoryStream();

            //存储到ms里面
            ImageFormat imgformat = ImageFormat.Png;
            if (geshi.ToLower().Contains("png"))
                imgformat = ImageFormat.Png;
            else if (geshi.ToLower().Contains("jpg") || geshi.ToLower().Contains("jpeg"))
                imgformat = ImageFormat.Jpeg;
            else if (geshi.ToLower().Contains("gif"))
                imgformat = ImageFormat.Gif;
            else if (geshi.ToLower().Contains("bmp"))
                imgformat = ImageFormat.Bmp;

            renderer.WriteToStream(qrCode.Matrix, imgformat, ms);


            return ms;
        }

        /// <summary>
        /// 得到图片缩略图
        /// </summary>
        /// <param name="img">图片对象</param>
        /// <param name="maxWidth">最大宽度</param>
        /// <param name="maxHeight">最大高度</param>
        /// <param name="isBlock">等比缩放</param>
        /// <param name="size">用时</param>
        /// <returns></returns>
        static System.Drawing.Image GetThumbImage(System.Drawing.Image img, int maxWidth, int maxHeight, bool isBlock, out float size)
        {
            int tWidth;
            int tHeight;
            size = 1;

            if (!isBlock)
            {
                tWidth = maxWidth;
                tHeight = maxHeight;
            }
            else
            {
                if (!(maxHeight > img.Height && maxWidth > img.Width))
                {
                    float HeightMultipier = (float)maxHeight / (float)img.Height;
                    float WidthMultipier = (float)maxWidth / (float)img.Width;
                    if (HeightMultipier > 1) HeightMultipier = 1;
                    if (WidthMultipier > 1) WidthMultipier = 1;
                    float SizeMultiplier = WidthMultipier < HeightMultipier ? WidthMultipier : HeightMultipier;
                    size = SizeMultiplier;
                    tWidth = (int)(img.Width * SizeMultiplier);
                    tHeight = (int)(img.Height * SizeMultiplier);
                }
                else
                {
                    tWidth = img.Width;
                    tHeight = img.Height;
                }
            }
            System.Drawing.Image bitmap = new System.Drawing.Bitmap(tWidth, tHeight);

            //新建一个画板
            Graphics g = System.Drawing.Graphics.FromImage(bitmap);

            //设置高质量插值法
            g.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.High;

            //设置高质量,低速度呈现平滑程度
            g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality;

            //清空画布并以透明背景色填充
            g.Clear(Color.Transparent);

            //在指定位置并且按指定大小绘制原图片的指定部分
            g.DrawImage(img, new Rectangle(0, 0, tWidth, tHeight),
                new Rectangle(0, 0, img.Width, img.Height),
                GraphicsUnit.Pixel);
            return bitmap;
        }

        /// <summary>
        /// 调用此函数后使此两种图片合并，类似相册，有个背景图，中间贴自己的目标图片  
        /// </summary>
        /// <param name="erweima"></param>
        /// <param name="photo"></param>
        /// <param name="width"></param>
        /// <returns></returns>
        public static MemoryStream erweimaPhoto(MemoryStream erweima, string photourl, string geshi = "png", int zoom = 4)
        {
            photourl = HttpContext.Current.Server.MapPath(photourl);

            if (!File.Exists(photourl))
            {
                return erweima;
            }
            Bitmap map = new Bitmap(erweima);//背景图片
            Graphics g = Graphics.FromImage(map);

            Image img = Image.FromFile(photourl);        //照片图片      

            int h = map.Height / zoom;
            int w = map.Width / zoom;
            if (img.Height > h || img.Height > h)//超过一半进行压缩
            {
                float time = 0;
                img = GetThumbImage(img, h, w, true, out time);
            }

            int x = (map.Width - img.Width) / 2;
            int y = (map.Height - img.Height) / 2;
            //g.DrawImage(img, 0, 0, img.Width, img.Height);
            g.DrawImageUnscaled(img, x, y, img.Width, img.Height);
            g.Dispose();


            MemoryStream ms = new MemoryStream();

            //存储到ms里面
            ImageFormat imgformat = ImageFormat.Png;
            if (geshi.ToLower().Contains("png"))
                imgformat = ImageFormat.Png;
            else if (geshi.ToLower().Contains("jpg") || geshi.ToLower().Contains("jpeg"))
                imgformat = ImageFormat.Jpeg;
            else if (geshi.ToLower().Contains("gif"))
                imgformat = ImageFormat.Gif;
            else if (geshi.ToLower().Contains("bmp"))
                imgformat = ImageFormat.Bmp;

            map.Save(ms, imgformat);

            if (map!=null) map.Dispose();
            return ms;
        }


        /// <summary>
        /// 调用此函数 在二维码上加入文字
        /// </summary>
        /// <param name="erweima"></param>
        /// <param name="photo"></param>
        /// <param name="width"></param>
        /// <returns></returns>
        public static MemoryStream erweimaText(MemoryStream erweima, string text, string geshi = "png", string font = "微软雅黑", string color = "#FFFFFF", string bgcolor = "#FE6D58", int fontsize = 30)
        {

            Bitmap map = new Bitmap(erweima);//背景图片

            int h = map.Height / 4;
            int w = map.Width / 4;

            Bitmap img = new Bitmap(h, w);//文字图片

            Graphics theGraphics = Graphics.FromImage(img);
            theGraphics.Clear(ColorTranslator.FromHtml(bgcolor));
            theGraphics.Clear(Color.Transparent);

            SolidBrush sdBrush1 = new SolidBrush(ColorTranslator.FromHtml(color));

            System.Drawing.Drawing2D.LinearGradientBrush newBrush = new System.Drawing.Drawing2D.LinearGradientBrush(new Rectangle(0, 0, img.Width, img.Height), ColorTranslator.FromHtml(color), ColorTranslator.FromHtml(color), 1.2f, true);

            Font theFont = new Font(font, w / fontsize, FontStyle.Bold);

            Point thePos = new Point(w / 2, h / 2);
            StringFormat sf = new StringFormat();
            sf.LineAlignment = StringAlignment.Center;
            sf.Alignment = StringAlignment.Center;
            theGraphics.DrawString(text, theFont, sdBrush1, thePos, sf);



            int x = (map.Width - img.Width) / 2;
            int y = (map.Height - img.Height) / 2;
            Graphics g = Graphics.FromImage(map);
            g.DrawImageUnscaled(img, x, y, img.Width, img.Height);





            MemoryStream ms = new MemoryStream();

            //存储到ms里面
            ImageFormat imgformat = ImageFormat.Png;
            if (geshi.ToLower().Contains("png"))
                imgformat = ImageFormat.Png;
            else if (geshi.ToLower().Contains("jpg") || geshi.ToLower().Contains("jpeg"))
                imgformat = ImageFormat.Jpeg;
            else if (geshi.ToLower().Contains("gif"))
                imgformat = ImageFormat.Gif;
            else if (geshi.ToLower().Contains("bmp"))
                imgformat = ImageFormat.Bmp;

            map.Save(ms, imgformat);
            g.Dispose();
            if (map != null) map.Dispose();
            return ms;
        }

        #endregion


        #region 极限验证

        private const String version = "2.15.7.23.1";
        private const String privateKey = "480d2832b98870a325a8b8ad72a56c6e";

        /// <summary>
        /// 极验验证 后台数据验证
        /// http://geetest.com/install/sections/idx-client-sdk.html#id2
        /// </summary>
        /// <param name="lxw"></param>
        public static bool JYvalidate(string challenge, string validate, string seccode)
        {
            string response = "";
            try
            {
                //string challenge = data.v_s("challenge");
                //string validate = data.v_s("validate");
                //string seccode = data.v_s("seccode");
                if (challenge.isnull() || validate.isnull() || seccode.isnull())
                    return false;
                if (!md5Encode(privateKey + "geetest" + challenge).Equals(validate))
                    return false;
                string query = "seccode=" + seccode + "&sdk=csharp_" + version;

                response = postValidate(query);
                string md5 = md5Encode(seccode);
                return response == md5;
            }
            catch (Exception err)
            {
                dataloger.fatal(err.Message, err);
            }
            return false;
        }

        /// <summary>
        /// 极验验证 请求服务器数据验证
        /// </summary>
        /// <param name="host"></param>
        /// <param name="path"></param>
        /// <param name="data"></param>
        /// <param name="port"></param>
        /// <returns></returns>
        static String postValidate(String data, int port = 80, string url = "http://api.geetest.com/validate.php")
        {
            //String url = host + path;
            System.Net.HttpWebRequest request = (System.Net.HttpWebRequest)System.Net.WebRequest.Create(url);
            request.Method = "POST";
            request.ContentType = "application/x-www-form-urlencoded";
            request.ContentLength = System.Text.Encoding.UTF8.GetByteCount(data);
            // 发送数据
            Stream myRequestStream = request.GetRequestStream();
            byte[] requestBytes = System.Text.Encoding.ASCII.GetBytes(data);
            myRequestStream.Write(requestBytes, 0, requestBytes.Length);
            myRequestStream.Close();

            System.Net.HttpWebResponse response = (System.Net.HttpWebResponse)request.GetResponse();
            // 读取返回信息
            Stream myResponseStream = response.GetResponseStream();
            StreamReader myStreamReader = new StreamReader(myResponseStream, System.Text.Encoding.GetEncoding("utf-8"));
            string retString = myStreamReader.ReadToEnd();
            myStreamReader.Close();
            myResponseStream.Close();

            return retString;

        }
        /// <summary>
        /// md5 加密
        /// </summary>
        /// <param name="plainText"></param>
        /// <returns></returns>
        static string md5Encode(String plainText)
        {
            System.Security.Cryptography.MD5CryptoServiceProvider md5 = new System.Security.Cryptography.MD5CryptoServiceProvider();
            string t2 = BitConverter.ToString(md5.ComputeHash(System.Text.UTF8Encoding.Default.GetBytes(plainText)));
            t2 = t2.Replace("-", "");
            t2 = t2.ToLower();
            return t2;
        }

        #endregion
    }
}